#ifndef __MSGID_H__
#define __MSGID_H__
/**
 *  @file  msgid.h
 *  @brief message ID definitions
 *
 */

/*
//|----------------------------------------------------------------------------
//|                 SKY NETWORKS CONFIDENTIAL - COPYRIGHT 2016
//|----------------------------------------------------------------------------
//| The information contained herein is the property of Sky Networks and is
//| strictly confidential. Except as expressly authorized in writing by Sky
//| Networks, the holder shall keep all information contained herein confiden-
//| tial, shall disclose it only to its employees with a need to know, and
//| shall protect it, in whole or in part, from disclosure and dissemination
//| to third parties with the same degree of care it uses to protect its own
//| confidential information of like nature, but with no less than reasonable
//| care. Except expressly authorized in writing by Sky Networks, the holder
//| is granted no rights to use the information contained herein.
//|----------------------------------------------------------------------------
*/

/*
//|----------------------------------------------------------------------------
//| Includes
//|----------------------------------------------------------------------------
*/
#include <inttypes.h>
#include <time.h>

/** Bits definitions */
#define _ID_NUM_BITS     (9)
#define _ID_GROUP_BITS   (8)
#define _ID_UNUSED_BITS  (13)
#define _ID_DIR_BITS     (2)

/** Mask definitions */
#define _ID_NUM_MASK     ((1<<_ID_NUM_BITS   )-1)
#define _ID_GROUP_MASK   ((1<<_ID_GROUP_BITS )-1)
#define _ID_UNUSED_MASK  ((1<<_ID_UNUSED_BITS)-1)
#define _ID_DIR_MASK     ((1<<_ID_DIR_BITS   )-1)

/** Shift definitions */
#define _ID_NUM_SHIFT    (0)
#define _ID_GROUP_SHIFT  (_ID_NUM_SHIFT    + _ID_NUM_BITS)
#define _ID_UNUSED_SHIFT (_ID_GROUP_SHIFT  + _ID_GROUP_BITS)
#define _ID_DIR_SHIFT    (_ID_UNUSED_SHIFT + _ID_UNUSED_BITS)

/** Message DIRECTION */
#define _ID_IN           ( (1 & _ID_DIR_MASK) << _ID_DIR_SHIFT)
#define _ID_OUT          ( (2 & _ID_DIR_MASK) << _ID_DIR_SHIFT)

typedef uint32_t idTypeNt;

/* Validation */
#ifdef __cplusplus
/* Does not work in C++ within switch statement ! */

/** Group validation */
#define _ID_GROUP_CHECK(group) \
        (\
         ((group&_ID_GROUP_MASK) << _ID_GROUP_SHIFT) \
        )

/** Number validation */
#define _ID_NUM_CHECK(num) \
        (\
         ((num&_ID_NUM_MASK) << _ID_NUM_SHIFT)\
        )
        
/** Payload size validation */
#define _ID_PAYLOAD_SIZE_CHECK(payload,maxlen) \
        (\
         0\
        )
        
#else
extern idTypeNt __invalid_id_group;
#define _ID_GROUP_CHECK(group) \
        (\
         ((uint32_t)group <= _ID_GROUP_MASK) ?\
         ((group&_ID_GROUP_MASK) << _ID_GROUP_SHIFT) :\
         __invalid_id_group\
        )

/** Number validation */
extern idTypeNt __invalid_id_num;
#define _ID_NUM_CHECK(num) \
        (\
         ((uint32_t)num <= _ID_NUM_MASK) ?\
         ((num&_ID_NUM_MASK) << _ID_NUM_SHIFT) :\
         __invalid_id_num\
        )

/** Payload size validation */
extern idTypeNt __invalid_id_payload_size;
#define _ID_PAYLOAD_SIZE_CHECK(payload,maxlen) \
        (\
         (payload <= maxlen) ?\
	     0 :\
         __invalid_id_payload_size\
        )
#endif

#define _ID_DIR_IN(pay_in) \
        (\
	     (pay_in == 0) ?\
	     0 : _ID_IN\
        )

#define _ID_DIR_OUT(pay_out) \
        (\
	     (pay_out == 0) ? \
	     0: _ID_OUT\
        )

#define _ID(group,num,pay_in,pay_out,maxlen) \
        ( (idTypeNt) \
           (\
             _ID_GROUP_CHECK(group) | \
	     _ID_NUM_CHECK(num) | \
	     _ID_PAYLOAD_SIZE_CHECK(pay_in,maxlen) |\
             _ID_PAYLOAD_SIZE_CHECK(pay_out,maxlen) |\
             _ID_DIR_IN(pay_in) |\
             _ID_DIR_OUT(pay_out)\
           )\
        )

/* Helper functions */

#define _ID_GET_NUM(id) ((id>>_ID_NUM_SHIFT)&_ID_NUM_MASK)

/** MSG ID macro */
#define MSG_ID(group,num,pay_in,pay_out)\
     _ID(group,num,pay_in,pay_out,MSG_MAX_PAYLOAD_LEN)

#endif /* __MSGID_H__ */
